#include "StdAfx.h"
#include "ServiceListener.h"
#include "SipInviteSession.hpp"
#include "SipInvB2bSession.hpp"
#include "SipSubB2bSession.hpp"
#include "SipSessionBase.hpp"
#include "ResipTesterDlg.h"
#include "SipTranSession.hpp"

#include "SipGDService.hpp"

#include <sstream>

CServiceListener::CServiceListener(CSipGDService& sv, CResipTesterDlg& dlg): 
m_dlg(dlg),
//m_realhandle(dlg),
m_service(sv)
{
    m_service.registerServiceListener(this);
}

CServiceListener::~CServiceListener(void)
{
}


///////////////// Dialog Listener  ///////////////////////////

bool CServiceListener::onRealPlay(CSipInviteSession& inv, SipMessage& msg)
{
    m_dlg.pushLogText(_T("Inviting.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents()){
        m_dlg.pushLogText(msg.getContents()->getBodyData().c_str(), m_dlg.m_BodyMonitor);
    }
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    std::string tar(msg.header(h_To).uri().user().c_str());
    std::string nameAddr = db->queryDevice(tar);
    const resip::Data& id = msg.getTransactionId();
    
    if (nameAddr.length() == 0)
    {
        inv.replyFail(id, CSipSessionBase::NonUser);
        m_dlg.pushLogText(_T("Invite Failed.\r\n"), m_dlg.m_MonitorEdit);
    } else 
    {
        int i = nameAddr.find("localhost");
        if (i >= 0)
        {
            CSipRealPlayHandler* realhandler = new CSipRealPlayHandler(m_dlg, inv, m_dlg.m_realList);
            inv.replyOK(id, std::string("OK Man."));
        } else
        {
            CSipInviteSession* NextInvs = m_service.realPlaySession(nameAddr);
            CSipInvB2bSession* invb2b = m_service.buildInvB2bSession(*NextInvs, inv);
            invb2b->startCaller(msg);
            //inv.replyTrying(id);
            m_dlg.pushLogText(_T("Invite b2bua.\r\n"), m_dlg.m_MonitorEdit);
        }
    }
    return true;
}

//bool CServiceListener::onPTZControl(CSipInviteSession& inv, SipMessage& msg){
//    return true;
//}

bool CServiceListener::onRegister(CSipRegisterSession& reg, SipMessage& msg)
{
    m_dlg.pushLogText(_T("Registering.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents())
    {
        std::string body(msg.getContents()->getBodyData().c_str());
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }
    
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    CSipRegisterHandler* reghandler = new CSipRegisterHandler(m_dlg, reg, m_dlg.m_regList);

    const resip::Data& id = msg.getTransactionId();
    //std::string remote = std::string(reg.getRemoteUri().host().c_str());
    if (!db->canForceFail())
    {
        reg.replyOK(id, std::string("Reg OK"));
    } else {
        reg.replyFail(id, CSipSessionBase::Rejected);
        m_dlg.pushLogText(_T("Register Rejected.\r\n"), m_dlg.m_MonitorEdit);
    }
    return true;
}


bool CServiceListener::onSubscribe(CSipSubscribeSession2& sub, SipMessage& msg)
{
    std::string body;
    m_dlg.pushLogText(_T("Subscrib coming.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents())
    {
        body = msg.getContents()->getBodyData().c_str();
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }

    const resip::Data& id = msg.getTransactionId();
    //int expires = msg.header(h_Expires).value();
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    CSipSubscribeHandler* hd = new CSipSubscribeHandler(m_dlg, sub, m_dlg.m_subList);

    if (db->canForceFail())
    {
        sub.replyFail(id, CSipSessionBase::Rejected);
        m_dlg.pushLogText(_T("Subscribe Rejected."), m_dlg.m_MonitorEdit);
    } else if (db->existDown() && db->canB2bDispatch())
    {
        std::string down = m_dlg.getSipUriDown();
        CSipSubscribeSession2* NextSubs = m_service.subscribeSession(down);
        CSipSubB2bSession* b2b = m_service.buildSubB2bSession(*NextSubs, sub);
        b2b->startCaller(msg);
    } else 
    {
        sub.replyOK(id, std::string("Sub OK."));
        m_dlg.pushLogText(_T("Subscribe OK."), m_dlg.m_MonitorEdit);
    }
    return true;
}


//bool CServiceListener::onNotify(CSipSubscribeSession2& sub, SipMessage& msg)
//{
//    /*m_dlg.pushLogText(_T("Notify coming.\r\n"), m_dlg.m_MonitorEdit);
//    std::string body(msg.getContents()->getBodyData().c_str());
//    m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
//    
//    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
//    if (!db->ForceFail()){
//        
//    }*/
//    return true;
//}

//////////// Transaction Listener  ////////////////////////

bool CServiceListener::onDevInfo(CSipSessionBase& s, SipMessage& msg)
{
    std::string body;
    m_dlg.pushLogText(_T("DevInfo coming.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents())
    {
        body = msg.getContents()->getBodyData().c_str();
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }

    CSipTranSession* wks = dynamic_cast<CSipTranSession*>(&s);
    std::string remote = std::string(s.getRemoteUri().host().c_str());
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    if (db->canForceFail())
    {
        if (wks){
            wks->replyFail(CSipSessionBase::Rejected);
        }
    } else if (db->canB2bDispatch())
    {
        CSipSessionHandler* nh = new CSipSessionHandler(m_dlg, m_dlg.m_tranList);
        m_service.sendDevInfo(m_dlg.getSipUriUp(), body, nh);
        if (wks){
            wks->replyOK(std::string("DevInfo OK"));
        }
    } else 
    {
        if (wks){
            wks->replyOK(std::string("DevInfo OK"));
        }
    } 
    return true;
}

bool CServiceListener::onStoreAlarm(CSipSessionBase& s, SipMessage& msg){
    return true;
}


bool CServiceListener::onDevCheck(CSipSessionBase& s, SipMessage& msg)
{
    return true;
}


bool CServiceListener::onEncodeSet(CSipSessionBase& s, SipMessage& msg)
{
    m_dlg.pushLogText(_T("EncodeSet coming.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents()){
        std::string body(msg.getContents()->getBodyData().c_str());
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }

    std::string tar(msg.header(h_To).uri().user().c_str());
    CSipTranSession* wks = dynamic_cast<CSipTranSession*>(&s);
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    std::string nameAddr = db->queryDevice(tar);
    if (wks){
        if (db->canForceFail())
        {
            wks->replyFail(CSipSessionBase::Rejected);
        } else {
            int i = nameAddr.find("localhost");
            if (i >= 0)
            {
                //wks->registerHandle(h);
                wks->replyOK(std::string("OK Man."));
            } else
            {
                std::string body;
                if (msg.getContents()){
                    body = msg.getContents()->getBodyData().c_str();
                }
                CSipB2bSessionHandler* h = new CSipB2bSessionHandler(*wks, m_dlg.m_b2bList);
                m_service.encodeSet(nameAddr, body, h);
                //inv.replyTrying(id);
                m_dlg.pushLogText(_T("Encode Set b2bua.\r\n"), m_dlg.m_MonitorEdit);
            }
        }
    }
    return true;
}

bool CServiceListener::onTimeSet(CSipSessionBase& s, SipMessage& msg)
{
    m_dlg.pushLogText(_T("TimeAdjust coming.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents()){
        std::string body(msg.getContents()->getBodyData().c_str());
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }

    CSipTranSession* wks = dynamic_cast<CSipTranSession*>(&s);
    std::string remote = std::string(s.getRemoteUri().host().c_str());
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    if (db->canForceFail())
    {
        if (wks){
            wks->replyFail(CSipSessionBase::Rejected);
        }
    } else if (db->canB2bDispatch())
    {
        if (wks){
            wks->replyOK(std::string("TimeAdjust OK"));
        }
        std::string body;
        if (msg.getContents()){
            body = msg.getContents()->getBodyData().c_str();
        }        
        CSipSessionHandler* nh = new CSipSessionHandler(m_dlg, m_dlg.m_tranList);
        m_service.timeAdjust(m_dlg.getSipUriDown(), body, nh);
    } else 
    {
        if (wks){
            wks->replyOK(std::string("TimeAdjust OK"));
        }
    } 
    return true;
}


bool CServiceListener::onTimeGet(CSipSessionBase& s, SipMessage& msg)
{
    return true;
}


bool CServiceListener::onFileListRequest(CSipSessionBase& s, SipMessage& msg)
{    
    m_dlg.pushLogText(_T("FileListRequest coming.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents())
    {
        std::string body(msg.getContents()->getBodyData().c_str());
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }

    CSipTranSession* wks = dynamic_cast<CSipTranSession*>(&s);
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    if (wks)
    {
        if (db->canForceFail())
        {
            wks->replyFail(CSipSessionBase::Rejected);
        } 
        else if (db->canB2bDispatch() && db->existDown())
        {
            std::string body;
            if (msg.getContents()){
                body = msg.getContents()->getBodyData().c_str();
            }
            CSipB2bSessionHandler* h = new CSipB2bSessionHandler(*wks, m_dlg.m_b2bList);
            m_service.fileListRequest(m_dlg.getSipUriDown(), body, h);
            m_dlg.pushLogText(_T("FileList b2bua.\r\n"), m_dlg.m_MonitorEdit);        
        } 
        else 
        {
            int count = m_dlg.getRespNumber();
            for (int i = 0; i < count; i++){
                std::ostringstream ostrm;
                ostrm << i;
                wks->replyOK(ostrm.str());
                //Sleep(1000);
            }
            wks->replyOK(std::string("Over Man."));
        }
    }
    return true;
}

bool CServiceListener::onFileUrlRequest(CSipSessionBase& s, SipMessage& msg){
    return true;
}

bool CServiceListener::onRecordPlanSet(CSipSessionBase& s, SipMessage& msg){
    return true;
}

bool CServiceListener::onRecordPlanList(CSipSessionBase& s, SipMessage& msg)
{
    m_dlg.pushLogText(_T("RecordPlanList coming.\r\n"), m_dlg.m_MonitorEdit);
    if (msg.getContents())
    {
        std::string body(msg.getContents()->getBodyData().c_str());
        m_dlg.pushLogText(body, m_dlg.m_BodyMonitor);
    }

    CSipTranSession* wks = dynamic_cast<CSipTranSession*>(&s);
    CDatabaseAdaptor* db = CDatabaseAdaptor::getInstance();
    if (wks)
    {
        if (db->canForceFail())
        {
            wks->replyFail(CSipSessionBase::Rejected);
        } 
        else if (db->canB2bDispatch() && db->existDown())
        {
            std::string body;
            if (msg.getContents()){
                body = msg.getContents()->getBodyData().c_str();
            }
            CSipB2bSessionHandler* h = new CSipB2bSessionHandler(*wks, m_dlg.m_b2bList);
            m_service.recordPlanList(m_dlg.getSipUriDown(), body, h);
            m_dlg.pushLogText(_T("PlanList b2bua.\r\n"), m_dlg.m_MonitorEdit);        
        } 
        else 
        {
            int count = m_dlg.getRespNumber();
            for (int i = 0; i < count; i++){
                std::ostringstream ostrm;
                ostrm << i;
                wks->replyOK(ostrm.str());
                //Sleep(1000);
            }
            wks->replyOK(std::string("Over Man."));
        }
    }
    return true;
}

bool CServiceListener::onRecordAction(CSipSessionBase& s, SipMessage& msg){
    return true;
}

